/* eslint-disable no-unused-vars */
import { KJUR } from 'jsrsasign'
import React, { useEffect, useRef } from 'react';

// import PropTypes from 'prop-types';


const getType = (fileUrl) => {
  if (!fileUrl) {
    return '';
  }

  const res =
    /\.([a-z0-9A-Z]{2,9})$/.exec(fileUrl) || /\.([a-z0-9A-Z]{2,9})(%3F|$|&|\?)/.exec(fileUrl);

  if (res) {
    return res[1].toLocaleLowerCase();
  }

  return '';
};


const calcToken = (tokenConfig, data) => {
  const header = { alg: 'HS256', typ: 'JWT' };
  const sHeader = JSON.stringify(header);
  // const sPayload = JSON.stringify(payload);
  const sPayload = JSON.stringify(
    {
      ...data,
      exp: KJUR.jws.IntDate.getNow() + tokenConfig.expiresIn
    }
  );
  const secret = tokenConfig.secret;

  const secretBase64 = secret;
  const sJWT = KJUR.jws.JWS.sign("HS256", sHeader, sPayload, secretBase64);
  return sJWT;
};

const hzeroBackMap = {};

window.top.addEventListener('message', (e) => {
  const _data = e.data;

  if(typeof _data !== 'string') {
      return;
  }
  if(!_data.startsWith('{')) {
      return;
  }

  const dataObj = JSON.parse(_data);

  if(dataObj.ctype !== 'hzero-callback') {
      return;
  }

  const key = dataObj.divId+dataObj.uuid;

  const cbCfg = hzeroBackMap[key];

  if(cbCfg) {
    delete hzeroBackMap[key];
    const cb = cbCfg.cb;
    cb(...(dataObj.args));
  }
});

const executeCommand = ({ args, cmdType, divId }) => {

  let _resolve = null;
  let _reject = null;
  const p = new Promise((resolve, reject) => {
    _resolve = resolve;
    _reject = reject;
  });

  let tid = null;

  const cb = (...args2) => {
    clearTimeout(tid);
    _resolve(...args2);
  };

  const uuid = `${(Date.now() + Math.random())}`;

  if(uuid) {
    const key = divId+uuid;
    tid = setTimeout(() => {
      const cbCfg = hzeroBackMap[key];
       if(cbCfg) {
        delete hzeroBackMap[key];
        _reject( new Error('timeout') );
       }
     }, 60000);
    hzeroBackMap[key] = {
      divId,
      cb,
    };
  }
  const doObj = {
    ctype: 'hzero',
    cmd: cmdType || 'executeCommand',
    args,
    divId,
    uuid,
  };

  const iframe = document.querySelector(`iframe[title=${divId}]`);
  const iframeWindow = iframe?.contentWindow;

  if(iframeWindow) {

    // if(!hzeroBackMap[divId]) {
    //   hzeroBackMap[divId] = true;
    //   // todo: 这里需要改成 其他方式通信
    //   // iframeWindow.addEventListener('message', (e) => {
    //   //   const _data = e.data;

    //   //   if(typeof _data !== 'string') {
    //   //       return;
    //   //   }
    //   //   if(!_data.startsWith('{')) {
    //   //       return;
    //   //   }

    //   //   const dataObj = JSON.parse(_data);

    //   //   if(dataObj.ctype !== 'hzero-callback') {
    //   //       return;
    //   //   }

    //   //   const key = dataObj.divId+dataObj.uuid;

    //   //   const cbCfg = hzeroBackMap[key];

    //   //   if(cbCfg) {
    //   //     delete hzeroBackMap[key];
    //   //     const cb = cbCfg.cb;
    //   //     cb(...(dataObj.args));
    //   //   }
    //   // });

    //   // iframeWindow.addEventListener('beforeunload', (e) => {
    //   //   delete hzeroBackMap[divId];
    //   // });
    // }

    iframeWindow.postMessage(JSON.stringify(doObj), '*');
  }
  

  return p;
};


// instance.executeCommand('command',`
//   (function()
//   {
//   const oDocument = Api.GetDocument();
//   oDocument.GetElement(3).GetRange(0,3).Select()
//   const aaa = oDocument.GetElement(3).GetRange(0,3).GetStartPos()
//   console.log({aaa});
//   return aaa;
//   // oDocument.GetRange(17, 78).Select()
//   // const aa = oDocument.GetRangeBySelect();
//   // console.log({aa})
//   })();
//   `).then(console.log, console.error);

// ooRef.current.executeMethod('PasteText',['abcde']).then(console.log, console.error);

const OnlyOfficeEditor = React.forwardRef(({
  documentUrl,
  documentType = 'text',
  config,
  onSave,
  tokenConfig,
  onError,
  style,
  className
}, ref) => {
  const editorRef = useRef(null);
  const editorInstance = useRef(null);
  const optionsRef = useRef(null);

  const divId = React.useMemo(() => `onlyoffice-editor-${Date.now()}`, []);

  React.useImperativeHandle(ref, () => ({
    // changeVal 就是暴露给父组件的方法
    getEditor: () => {
       return editorInstance.current
    },
    executeCommand: (...args) => {
      return executeCommand({ divId, args });
    },
    executeMethod: (...args) => {
      return executeCommand({
        args,
        divId,
        cmdType: 'executeMethod'
      });
    },
    executeDomApi: (domJs) => {
      return executeCommand({
        args: [domJs],
        divId,
        cmdType: 'executeDomApi'
      });
    },
    // openFile: handleOpenFile,
  //   openFile: (newFileUrl) => {
  //     const newOptions = cloneDeep(optionsRef.current);

  //     // delete newOptions.documentType;
  //     // delete newOptions.type;
  //     // delete newOptions.events;

  //     newOptions.document.url = newFileUrl;

  //     // const fileKey = Date.now().toString();
  //     // sessionStorage.setItem(documentUrl, fileKey);
  //     // newOptions.document.key = fileKey;
  //     // sessionStorage.setItem(newFileUrl, fileKey);

  //     const fileKey = sessionStorage.getItem(documentUrl) || optionsRef.current.document.key;
  //     sessionStorage.setItem(newFileUrl, fileKey);

  //     if (tokenConfig?.enable) {
  //       delete newOptions.token;
  //       delete newOptions.document.token;
  //       // 创建 JWT
  //       const jwtToken = calcToken(tokenConfig, newOptions);
  //       newOptions.token = jwtToken;
  //     }

  //     // debugger;

  //     editorInstance.current.refreshFile({
  //       document: {
  //         fileType: newOptions.document.fileType,
  //         key: newOptions.document.key,
  //         title: newOptions.document.title,
  //         url: newOptions.document.url,
  //       },
  //       documentType: newOptions.documentType,
  //       editorConfig: newOptions.editorConfig,
  //       token: newOptions.token
  //     });
  //     // optionsRef.current = newOptions;

  //  }
  }));

  // 初始化 OnlyOffice
  const initEditor = () => {

    if (editorInstance.current) {

      if(optionsRef.current.document.url === documentUrl) {
        return;
      }

      sessionStorage.removeItem(documentUrl);
      editorInstance.current.destroyEditor();
      editorInstance.current = null;
    }

    let fileKey = sessionStorage.getItem(documentUrl);

    if(!fileKey) {
      fileKey = Date.now().toString();
      sessionStorage.setItem(documentUrl, fileKey);
    }
  
    const editorConfig = {
      document: {
        fileType: getType(documentUrl) ||  'docx',
        key: fileKey,
        title: config.title || `Document-${Date.now()}`,
        url: documentUrl,
        permissions: {
          chat: false,
          comment: true,
        }
      },
      title: divId,
      token: config.token,
      type: 'desktop',
      // documentType: documentType === 'rtf' ? 'text' : 'word',
      editorConfig: {
        mode: "edit",
        lang: config.lang || 'zh',
        callbackUrl: config.callbackUrl,
        user: config.user || { id: 'anonymous' },
        customization: {
          autosave: true,
          comments: true,
          hideRightMenu: true,
          // compactToolbar: true,
          layout: {
            toolbar: {
              // 协作菜单去不到， 如果想要去掉， 想要换开发者版本
              collaboration: {
                mailmerge: true,
              },
            },
          },
          // plugins: false,
          ...config.customization
        },
      
        plugins: {
          // autostart: [
          //   // "asc.{0616AE85-5DBE-4B6B-A0A9-455C4F1503A1}",
          //   "asc.{0616AE85-5DBE-4B6B-A0A9-455C4F1503AD}",
          // ],
          // 插件中通过 window.Asc.plugin.info.options 可以读取
          options: {
            "all": {
              // keyAll: "valueAll",
              divId,
            },
            // "asc.{0616AE85-5DBE-4B6B-A0A9-455C4F1503AD}": {
            //   divId,
            // },
          },
          // pluginsData: [
          //   `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}/oo-plugins/helloworld/config.json`,
          // ],
        },

        // coEditing: {
        //   mode: 'strict',
        //   change: false
        // },
      },

      events: {
        ...config.events
      },

      height: '100%',
      width: '100%'
    };
    
    if (tokenConfig?.enable) {
      // 生成 JWT
      // const jwt = require('jsonwebtoken');
      // config.token = jwt.sign(config, tokenConfig.secret, { expiresIn: tokenConfig.expiresIn });
    
      delete editorConfig.token;
      // 创建 JWT
      const jwtToken = calcToken(tokenConfig, editorConfig);
      editorConfig.token = jwtToken;
    }
    optionsRef.current = editorConfig;
    
    editorInstance.current = new window.DocsAPI.DocEditor(
      editorRef.current.id,
      editorConfig
    );
  };


  // 加载 OnlyOffice API 脚本
  useEffect(() => {

    if (window.DocsAPI) {
      initEditor()
      return;
    } else {
      
      if(window.isInjectOoscript) {
        if (window.DocsAPI) {
          initEditor()
          return;
        } 
      }
      window.isInjectOoscript = true;

      window._ooHost = config.apiUrl;
      const script = document.createElement('script');
      const ooApiScriptjs = `${config.apiUrl}/web-apps/apps/api/documents/api.js`;
      // const ooApiScriptjs = `/oo-api.js`;
      script.src = ooApiScriptjs;
      script.async = true;

      script.onload = () => initEditor();
      script.onerror = (error) => onError?.(error);
      
      document.head.appendChild(script);
  
      return () => {
        // document.head.removeChild(script);
        if (editorInstance.current) {
          editorInstance.current.destroyEditor();
        }
      };
    }
  }, [documentUrl]);

  return (
    <div
      ref={editorRef}
      id={divId}
      style={{ height: '600px', ...style }}
      className={className}
    />
  );
});

// OnlyOfficeEditor.propTypes = {
//   documentUrl: PropTypes.string.isRequired,
//   documentType: PropTypes.oneOf(['rtf', 'docx']),
//   config: PropTypes.shape({
//     apiUrl: PropTypes.string.isRequired,
//     callbackUrl: PropTypes.string.isRequired,
//     user: PropTypes.object,
//     customization: PropTypes.object
//   }).isRequired,
//   onSave: PropTypes.func,
//   onError: PropTypes.func,
//   style: PropTypes.object,
//   className: PropTypes.string
// };

export default OnlyOfficeEditor;



//  if(!window['boundInternalcommand']){

//                 // window.Asc.plugin.info.options // 获取 editorConfig.plugins.options 的数据

//                 window.top.addEventListener('message', (e) => {
//                     const _data = e.data;
            
//                     if(typeof _data !== 'string') {
//                         return;
//                     }
//                     if(!_data.startsWith('{')) {
//                         return;
//                     }
            
//                     const dataObj = JSON.parse(_data);
            
//                     if(dataObj.ctype !== 'hzeroc') {
//                         return;
//                     }

//                     if(window.Asc.plugin.info.options) {
//                         if(window.Asc.plugin.info.options.divId !== dataObj.divId) {
//                             return;
//                         }
//                     }

//                     let callBack = undefined;

//                     if(dataObj.uuid) {
//                         callBack = (...args) => {
//                             const doObj = {
//                                 ctype: 'hzeroc-callback',
//                                 uuid: dataObj.uuid,
//                                 args,
//                                 divId: dataObj.divId
//                             };
//                             window.top.postMessage(JSON.stringify(doObj), '*');
//                         };
//                     }
            
//                     // 如果需要自定义插件的功能, 只需要在这个方法里接受参数写逻辑就行
//                     var command = dataObj.cmd;
//                     var res = eval(command);
//                     if(callBack) {
//                         callBack(res);
//                     }
//                 });
//                 window['boundInternalcommand'] = true;
//             }